package com.foreverwin.jzymes.common.service.impl;

import com.foreverwin.jzymes.common.constant.Constants;
import com.foreverwin.jzymes.common.mapper.ProductionShiftAdviceMapper;
import com.foreverwin.jzymes.common.service.IProductionShiftService;
import com.foreverwin.jzymes.common.service.ISystemRuleAdviceService;
import com.foreverwin.jzymes.common.util.BOHandleUtil;
import com.foreverwin.jzymes.framework.exception.BusinessException;
import com.foreverwin.jzymes.framework.util.DateUtil;
import com.foreverwin.jzymes.framework.util.I18nUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class ProductionShiftServiceImpl implements IProductionShiftService {

    @Autowired
    ISystemRuleAdviceService systemRuleAdviceService;
    @Autowired
    ProductionShiftAdviceMapper productionShiftAdviceMapper;

    /**
     * 查询工作日日期边界
     *
     * @param site
     * @return
     */
    public Date[] findProductionDayRange( String site ){
        Assert.hasText( site, I18nUtil.getI18nText( "common.siteNotBlank" ) );

        Date[] dateRange = new Date[2];
        int[] timeRange = null;
        List<Map<String,Object>> productionShiftList = findShiftList( site );
        for( Map<String,Object> productionShift : productionShiftList ){

            int startTime = ((BigDecimal) productionShift.get( "START_TIME" )).intValue();
            int endTime = ((BigDecimal) productionShift.get( "END_TIME" )).intValue();

            if( startTime > endTime ){
                endTime = endTime + 2400;
            }

            if( timeRange == null ){
                timeRange = new int[2];
                timeRange[0] = startTime;
                timeRange[1] = endTime;
                continue;
            }

            if( startTime < timeRange[0] ){
                timeRange[0] = startTime;
            }

            if( endTime > timeRange[1]  ){
                timeRange[1] = endTime;
            }
        }

        Date crrentDay = new Date();
        Long currentTime = Long.valueOf( DateUtil.format( crrentDay, "HHmm" ) );
        if( currentTime < timeRange[0] ){
            dateRange[0] = DateUtils.truncate( crrentDay, Calendar.DAY_OF_MONTH );
            dateRange[0] = DateUtils.addDays( dateRange[0], -1 );
            dateRange[0] = DateUtils.setHours( dateRange[0], timeRange[0] / 100 );
            dateRange[0] = DateUtils.setMinutes( dateRange[0], timeRange[0] % 100 );
        }else{
            dateRange[0] = DateUtils.truncate( crrentDay, Calendar.DAY_OF_MONTH );
            dateRange[0] = DateUtils.setHours( dateRange[0], timeRange[0] / 100 );
            dateRange[0] = DateUtils.setMinutes( dateRange[0], timeRange[0] % 100 );
        }

        if( timeRange[1] > 2400 ){
            dateRange[1] = DateUtils.truncate( crrentDay, Calendar.DAY_OF_MONTH );
            dateRange[1] = DateUtils.addDays( dateRange[1], 1 );
            dateRange[1] = DateUtils.setHours( dateRange[1], ( timeRange[1] - 2400 ) / 100 );
            dateRange[1] = DateUtils.setMinutes( dateRange[1], ( timeRange[1] - 2400 ) % 100 );
        }else {
            dateRange[1] = DateUtils.truncate( crrentDay, Calendar.DAY_OF_MONTH );
            dateRange[1] = DateUtils.setHours( dateRange[1], timeRange[1] / 100 );
            dateRange[1] = DateUtils.setMinutes( dateRange[1], timeRange[1] % 100 );
        }

        return dateRange;
    }

    /**
     * 查询班次日期边界
     *
     * @param site
     * @param shift
     * @return
     */
    public Date[] findShiftRange( String site, String shift ){
        Date crrentDay = new Date();
        return findShiftRange( site, shift, crrentDay );
    }

    /**
     * 查询班次日期边界
     *
     * @param site
     * @param shift
     * @return
     */
    public Date[] findShiftRange( String site, String shift, Date date ){
        Assert.hasText( site, I18nUtil.getI18nText( "common.siteNotBlank" ) );
        Assert.hasText( shift, I18nUtil.getI18nText( "common.productionShiftNotBlank" ) );

        Date[] dateRange = new Date[2];
        boolean exist = false;
        List<Map<String,Object>> productionShiftList = findShiftList( site );
        for( Map<String,Object> map : productionShiftList ){
            if( shift.equalsIgnoreCase( (String) map.get( "PRODUCTION_SHIFT" ) ) ){
                exist = true;

                int currentTime = Integer.valueOf( DateUtil.format( date, "HHmm" ) );
                int startTime = ((BigDecimal) map.get( "START_TIME" )).intValue();
                int endTime = ((BigDecimal) map.get( "END_TIME" )).intValue();
                dateRange[0] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( startTime+"", 4, "0" ), "yyyyMMddHHmm" );
                if( endTime < startTime ){
                    if( currentTime >= startTime ){
                        dateRange[1] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( endTime+"", 4, "0" ), "yyyyMMddHHmm" );
                        dateRange[1] = DateUtil.addDays( dateRange[1], 1 );
                    }else if( currentTime < endTime ){
                        dateRange[0] = DateUtil.addDays( dateRange[0], -1 );
                        dateRange[1] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( endTime+"", 4, "0" ), "yyyyMMddHHmm" );
                    }else{
                        throw BusinessException.build("common.productionShiftNotContainDate", new String[]{ DateUtil.format(date), shift } );
                    }
                }else{
                    dateRange[1] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( endTime+"", 4, "0" ), "yyyyMMddHHmm" );
                }
            }
        }

        if( !exist ){
            throw BusinessException.build("common.productionShiftNotExist", new String[]{ shift } );
        }
        return dateRange;
    }

    /**
     * 查询班次日期边界
     *
     * @param site
     * @param date
     * @return
     */
    public Date[] findShiftRange( String site, Date date ){
        Date[] dateRange = new Date[2];
        List<Map<String,Object>> productionShiftList = findShiftList( site );
        Long currentTime = Long.valueOf( DateUtil.format( date, "HHmm" ) );
        String shift = null;
        for( Map<String,Object> map : productionShiftList ){
            Long startTime = ((BigDecimal) map.get( "START_TIME" )).longValue();
            Long endTime = ((BigDecimal) map.get( "END_TIME" )).longValue();
            if( endTime < startTime ){
                if( currentTime >= startTime ){
                    dateRange[0] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( startTime+"", 4, "0" ), "yyyyMMddHHmm" );
                    dateRange[1] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( endTime+"", 4, "0" ), "yyyyMMddHHmm" );
                    dateRange[1] = DateUtil.addDays( dateRange[1], 1 );
                    shift = (String) map.get( "PRODUCTION_SHIFT" );
                    break;
                }
                if( currentTime < endTime ){
                    dateRange[0] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( startTime+"", 4, "0" ), "yyyyMMddHHmm" );
                    dateRange[0] = DateUtil.addDays( dateRange[0], -1 );
                    dateRange[1] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( endTime+"", 4, "0" ), "yyyyMMddHHmm" );
                    shift = (String) map.get( "PRODUCTION_SHIFT" );
                }
            }else{
                if( currentTime >= startTime && currentTime < endTime ){
                    dateRange[0] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( startTime+"", 4, "0" ), "yyyyMMddHHmm" );
                    dateRange[1] = DateUtil.parse( DateUtil.format( date, "yyyyMMdd" ) + StringUtils.leftPad( endTime+"", 4, "0" ), "yyyyMMddHHmm" );
                    shift = (String) map.get( "PRODUCTION_SHIFT" );
                    break;
                }
            }
        }
        if( StringUtils.isBlank( shift ) ){
            throw BusinessException.build("common.productionShiftOnDateNotExist", new Object[]{ date } );
        }
        return dateRange;
    }

    /**
     * 查询日期生产班次
     *
     * @param site
     * @param date
     * @return
     */
    public String findShift( String site, Date date ){
        List<Map<String,Object>> productionShiftList = findShiftList( site );
        Long currentTime = Long.valueOf( DateUtil.format( date, "HHmm" ) );
        String shift = null;
        for( Map<String,Object> map : productionShiftList ){
            Long startTime = ((BigDecimal) map.get( "START_TIME" )).longValue();
            Long endTime = ((BigDecimal) map.get( "END_TIME" )).longValue();
            if( endTime < startTime ){
                if( currentTime >= startTime || currentTime < endTime ){
                    shift = (String) map.get( "PRODUCTION_SHIFT" );
                    break;
                }
            }else{
                if( currentTime >= startTime && currentTime < endTime ){
                    shift = (String) map.get( "PRODUCTION_SHIFT" );
                    break;
                }
            }
        }
        if( StringUtils.isBlank( shift ) ){
            throw BusinessException.build("common.productionShiftOnDateNotExist", new Object[]{ date } );
        }
        return shift;
    }


    public List<Map<String,Object>> findShiftList( String site ){
        String shiftDayType = systemRuleAdviceService.existSystemRule( site, Constants.SYSTEM_RULE_SHIFT_DAY_TYPE );
        String productionDayTypeBo = BOHandleUtil.buildProductionDayType( site, shiftDayType );
        List<Map<String,Object>> productionShiftList = productionShiftAdviceMapper.selectProductionShift( productionDayTypeBo );

        Assert.isTrue( productionShiftList != null && productionShiftList.size() > 0, I18nUtil.getI18nText( "common.productionShiftNotEmpty" ) );
        return productionShiftList;
    }

}
